home *** CD-ROM | disk | FTP | other *** search
- /*
- ** CustomRequest.c
- **
- ** EasyRequest like custom requester
- **
- ** Copyright © 1990-1996 by Olaf `Olsen' Barthel
- ** All Rights Reserved
- **
- ** :ts=4
- */
-
- #ifndef _GLOBAL_H
- #include "Global.h"
- #endif
-
- /* GetScreenInfo():
- *
- * Obtain the currently visible screen area.
- */
-
- STATIC VOID
- GetScreenInfo(struct Screen *Screen,WORD *Left,WORD *Top,WORD *Width,WORD *Height)
- {
- struct ViewPortExtra *Extra;
- struct TagItem Tags[2] = { VTAG_VIEWPORTEXTRA_GET, NULL, TAG_DONE };
-
- if(!VideoControl(Screen -> ViewPort . ColorMap,Tags))
- Extra = (struct ViewPortExtra *)Tags[0] . ti_Data;
- else
- Extra = NULL;
-
- if(!Extra)
- Extra = Screen -> ViewPort . ColorMap -> cm_vpe;
-
- if(!Extra)
- Extra = (struct ViewPortExtra *)GfxLookUp(&Screen -> ViewPort);
-
- if(Extra)
- {
- struct Rectangle Clip;
-
- QueryOverscan(GetVPModeID(&Screen -> ViewPort),&Clip,OSCAN_TEXT);
-
- *Width = Extra -> DisplayClip . MaxX - Extra -> DisplayClip . MinX + 1;
- *Height = Extra -> DisplayClip . MaxY - Extra -> DisplayClip . MinY + 1;
-
- if(*Width < Clip . MaxX - Clip . MinX + 1)
- *Width = Clip . MaxX - Clip . MinX + 1;
-
- if(*Height < Clip . MaxY - Clip . MinY + 1)
- *Height = Clip . MaxY - Clip . MinY + 1;
- }
- else
- {
- *Width = Screen -> Width;
- *Height = Screen -> Height;
- }
-
- *Left = ABS(Screen -> LeftEdge);
- *Top = ABS(Screen -> TopEdge);
-
- if(*Left > Screen -> Width || *Left < 0)
- *Left = 0;
-
- if(*Top > Screen -> Height || *Top < 0)
- *Top = 0;
- }
-
- /* CentreWindow():
- *
- * Centre a window within the visible bounds of
- * a screen.
- */
-
- STATIC VOID
- CentreWindow(struct Screen *Screen,WORD Width,WORD Height,WORD *Left,WORD *Top)
- {
- WORD ScreenWidth,ScreenHeight,ScreenLeft,ScreenTop;
-
- GetScreenInfo(Screen,&ScreenLeft,&ScreenTop,&ScreenWidth,&ScreenHeight);
-
- *Left = ScreenLeft + (ScreenWidth - Width) / 2;
- *Top = ScreenTop + (ScreenHeight - Height) / 2;
- }
-
- STATIC VOID __saveds __asm
- StuffText(REG(a3) LONG *Data,REG(d0) UBYTE Char)
- {
- STRPTR Buffer = (STRPTR)Data[0]; // Space allocated for the char buffer
- struct IntuiText *IText = (APTR)Data[1]; // Space allocated for the IntuiTexts
-
- if(Char == Data[2] || Char == '\0')
- {
- LONG Width;
-
- IText -> LeftEdge = 0;
- IText -> TopEdge = Data[3]; // Text top edge
- IText -> ITextFont = NULL;
-
- // Line height, derived from font size
-
- Data[3] += Data[4];
-
- // Chop off the rest
-
- *Buffer++ = '\0';
-
- // Measure the length in pixels
-
- if(Data[6])
- {
- Width = TextLength((APTR)Data[6],IText -> IText,(LONG)Buffer - (LONG)IText -> IText - 1);
-
- // More than we got before?
-
- if(Width > Data[5])
- Data[5] = Width;
- }
-
- if(Char != '\0')
- {
- // Link to following text
-
- IText -> NextText = IText + 1;
-
- // Get ready for the next line
-
- Data[1] = (LONG)(++IText);
-
- // Start of next line
-
- IText -> IText = Buffer;
- }
- else
- IText -> NextText = NULL; // Terminate the chain
- }
- else
- *Buffer++ = Char; // Just store the character
-
- Data[0] = (LONG)Buffer; // Remember for next char
- }
-
- STATIC VOID __asm
- CountChar(REG(a3) LONG *Count,REG(d0) UBYTE Char)
- {
- if(Char == Count[2] || Char == '\0') // Count the number of lines
- Count[1]++;
-
- Count[0]++; // Count the number of characters in total
- }
-
- STATIC struct IntuiText *
- BuildITextTable(STRPTR FormatString,va_list VarArgs,UBYTE Terminator,LONG *Information,LONG *MoreData)
- {
- struct IntuiText *Primitive;
-
- Information[0] = Information[1] = 0;
- Information[2] = Terminator;
-
- RawDoFmt(FormatString,VarArgs,(VOID (*)())CountChar,Information);
-
- if(Primitive = (struct IntuiText *)AllocVec(Information[1] * sizeof(struct IntuiText) + Information[0],MEMF_ANY))
- {
- // Room for the char buffer
-
- MoreData[0] = (LONG)(Primitive + Information[1]);
-
- // Room for the IntuiTexts
-
- MoreData[1] = (LONG)Primitive;
-
- // Separator char to use
-
- MoreData[2] = Terminator;
-
- // Top edge of first text, the following lines get placed below
-
- MoreData[3] = 0;
-
- // The maximum width of all lines will end up here
-
- MoreData[5] = 0;
-
- // Now this is important; the first IText buffer must
- // be set up here, the formatting code will do the rest
- // for all the others
-
- Primitive[0].IText = (STRPTR)MoreData[0];
- }
-
- return(Primitive);
- }
-
- /* ShowInfo():
- *
- * Display an EasyRequest like information requester.
- */
-
- LONG __stdargs
- ShowInfo(struct Window *Parent,STRPTR Title,STRPTR Continue,STRPTR FormatString,...)
- {
- struct Screen *Screen;
- ULONG IntuiLock;
- LONG Result = 0;
- BOOL PopBack;
-
- if(Parent)
- Screen = Parent -> WScreen;
- else
- Screen = LockPubScreen(NULL);
-
- IntuiLock = LockIBase(NULL);
-
- PopBack = (BOOL)(IntuitionBase -> FirstScreen != Screen);
-
- UnlockIBase(IntuiLock);
-
- if(Screen)
- {
- struct DrawInfo *DrawInfo;
-
- if(PopBack)
- ScreenToFront(Screen);
-
- if(DrawInfo = GetScreenDrawInfo(Screen))
- {
- struct TextAttr FontTemplate;
- va_list VarArgs;
- LONG Information[3],GadgetInformation[3];
- LONG MoreData[7],GadgetData[7];
- struct IntuiText *BodyText;
- struct IntuiText *GadgetText;
- struct Gadget **GadgetTable;
- struct Image *GadgetFrameImage;
- LONG DistX,DistY;
- LONG FullButtonWidth;
- struct TextFont *Font;
- LONG RoomX,RoomY;
-
- // We'll need this one later
-
- Font = DrawInfo->dri_Font;
-
- // Set up the spacing information
-
- RoomY = (Font->tf_YSize + 1) / 2;
- RoomX = (RoomY * DrawInfo->dri_Resolution.Y) / DrawInfo->dri_Resolution.X;
-
- // Make a copy of the screen font
-
- AskFont(&Screen->RastPort,&FontTemplate);
-
- // Request that it be boldfaced, the leftmost
- // button will receive this type of label
-
- FontTemplate.ta_Style |= FSF_BOLD;
-
- va_start(VarArgs,FormatString);
- BodyText = BuildITextTable(FormatString,VarArgs,'\n',Information,MoreData);
- va_end(VarArgs);
-
- GadgetText = BuildITextTable(Continue,NULL,'|',GadgetInformation,GadgetData);
-
- GadgetTable = (struct Gadget **)AllocVec(sizeof(struct Gadget *) * GadgetInformation[1],MEMF_ANY|MEMF_CLEAR);
-
- GadgetFrameImage = (struct Image *)NewObjectA(NULL,FRAMEICLASS,NULL);
-
- if(GadgetFrameImage && GadgetTable && GadgetText)
- {
- LONG ID = 0,Last = GadgetInformation[1] - 1,i;
- struct Gadget *Previous = NULL;
- ULONG PrevTag = TAG_IGNORE;
-
- // We'll work with the button sizes in a minute...
-
- FullButtonWidth = 0;
-
- // We don't want fonts to be measured
-
- GadgetData[6] = 0;
-
- RawDoFmt(Continue,NULL,(VOID (*)())StuffText,GadgetData);
-
- DistY = 2;
- DistX = (DistY * DrawInfo->dri_Resolution.Y) / DrawInfo->dri_Resolution.X;
-
- GadgetText[0].ITextFont = &FontTemplate;
-
- for(i = 0 ; i <= Last ; i++)
- {
- if(i == Last)
- ID = 0;
- else
- ID++;
-
- GadgetText[i].NextText = NULL;
-
- if(GadgetTable[i] = NewObject(NULL,FRBUTTONCLASS,
- GA_IntuiText, &GadgetText[i],
- GA_Image, GadgetFrameImage,
- GA_RelVerify, TRUE,
- GA_ID, ID,
- GA_DrawInfo, DrawInfo,
- PrevTag, Previous,
- TAG_DONE))
- {
- Previous = GadgetTable[i];
- PrevTag = GA_Previous;
-
- SetAttrs(Previous,
- GA_Width, 2*DistX + Previous->Width,
- GA_Height, 2*DistY + Previous->Height,
- GA_DrawInfo,DrawInfo,
- TAG_DONE);
-
- // Add the width of the button, plus
- // some room in between
-
- FullButtonWidth += Previous->Width + RoomX;
- }
- else
- {
- LONG j;
-
- for(j = 0 ; j < i ; j++)
- DisposeObject(GadgetTable[i]);
-
- FreeVec(GadgetTable);
- GadgetTable = NULL;
-
- break;
- }
- }
-
- // Subtract the trailing space, add the border space
-
- FullButtonWidth += Screen->WBorRight + RoomX + Screen->WBorLeft;
- }
-
- // Did we get what we wanted and will the buttons fit on
- // the screen?
-
- if(BodyText && GadgetText && GadgetTable && FullButtonWidth <= Screen->Width)
- {
- WORD Width,Height,Left,Top;
-
- WORD WindowWidth,WindowHeight,
- ScreenWidth,ScreenHeight,
- ScreenLeft,ScreenTop;
-
- struct Image *FillImage,
- *FrameImage,
- *TextImage;
-
- LONG FullTitleWidth;
-
- ULONG DepthWidth;
- struct Image *DepthImage;
-
- // Before we do anything else, set up the
- // full width of the window title; this includes
- // both the text and the depth arrangement gadget
-
- if(Title)
- FullTitleWidth = TextLength(&Screen->RastPort,Title,strlen(Title));
- else
- FullTitleWidth = 0;
-
- // Get the width of the window depth gadget for this screen
-
- if(DepthImage = NewObject(NULL,SYSICLASS,
- SYSIA_Size, (Screen->Flags & SCREENHIRES) ? SYSISIZE_MEDRES : SYSISIZE_LOWRES,
- SYSIA_Which, DEPTHIMAGE,
- SYSIA_DrawInfo, DrawInfo,
- TAG_DONE))
- {
- GetAttr(IA_Width,DepthImage,&DepthWidth);
-
- DisposeObject(DepthImage);
- }
- else
- DepthWidth = (Screen->Flags & SCREENHIRES) ? 23 : 17;
-
- FullTitleWidth += DepthWidth + 2;
-
- if(FullTitleWidth > Screen -> Width)
- FullTitleWidth = Screen -> Width;
-
- // Increase the size to fit all the buttons into the window
-
- if(FullButtonWidth > FullTitleWidth)
- FullTitleWidth = FullButtonWidth;
-
- // Height of each line
-
- MoreData[4] = Font->tf_YSize;
-
- // Pointer to screen rastport used for measuring the text
-
- MoreData[6] = (LONG)&Screen->RastPort;
-
- // Now do the magic formatting...
-
- va_start(VarArgs,FormatString);
- RawDoFmt(FormatString,VarArgs,(VOID (*)())StuffText,MoreData);
- va_end(VarArgs);
-
- // The maximum width of all lines is now in MoreData[5],
- // the effective height of the block in MoreData[3];
-
- TextImage = NewObject(NULL,ITEXTICLASS,
- IA_FGPen, DrawInfo->dri_Pens[TEXTPEN],
- IA_Data, BodyText,
- IA_Width, MoreData[5] + 2*DistX, // Add a little room around the text
- IA_Height, MoreData[3] + 2*DistY,
- TAG_DONE);
-
- // Build the checkered background fill pattern
-
- FillImage = NewObject(NULL,FILLRECTCLASS,
- IA_APattern, &Crosshatch,
- IA_APatSize, 1,
- IA_Mode, JAM2,
- IA_FGPen, DrawInfo->dri_Pens[SHINEPEN],
- IA_BGPen, DrawInfo->dri_Pens[BACKGROUNDPEN],
- TAG_DONE);
-
- // Do the same for the frame around the text
-
- FrameImage = NewObject(NULL,FRAMEICLASS,
- IA_Recessed, TRUE,
- TAG_DONE);
-
- // Did we get 'em all?
-
- if(FillImage && FrameImage && TextImage)
- {
- struct Gadget Dummy;
- struct IBox FramedSize;
- LONG WindowLeft,
- WindowTop;
- struct Window *Window;
-
- // We'll need these offsets pretty soon
-
- WindowLeft = Screen->WBorLeft;
- WindowTop = Screen->WBorTop + Screen->Font->ta_YSize + 1;
-
- // Now check how large the surrounding frame would be
-
- DoMethod((Object *)FrameImage,IM_FRAMEBOX,&TextImage->LeftEdge,&FramedSize,DrawInfo,NULL);
-
- // Pad the space around the frame a bit
-
- FramedSize.Width += 2 * RoomX;
- FramedSize.Height += 2 * RoomY;
-
- // Save these for the window open stuff
-
- Width = WindowLeft + FramedSize.Width + Screen->WBorRight;
- Height = WindowTop + FramedSize.Height + Screen->WBorBottom;
-
- // If the window title won't fit on the screen,
- // expand the fillimage a bit; do the same to the
- // textimage.
-
- if(Width < FullTitleWidth)
- {
- LONG Adapt = (FullTitleWidth - Width + 1) & ~1;
-
- FramedSize.Width += Adapt;
- Width += Adapt;
-
- DistX += Adapt / 2;
-
- SetAttrs((Object *)TextImage,
- IA_Width,MoreData[5] + 2*DistX,
- TAG_DONE);
- }
-
- // Adjust size and position of the background pattern
-
- SetAttrs((Object *)FillImage,
- IA_Left, WindowLeft,
- IA_Top, WindowTop,
- IA_Width, FramedSize.Width,
- IA_Height, FramedSize.Height,
- TAG_DONE);
-
- // Do the whole thing all over again for the framed text;
- // this will put the right coords to centre the text within
- // the frame into FramedSize
-
- DoMethod((Object *)FrameImage,IM_FRAMEBOX,&TextImage->LeftEdge,&FramedSize,DrawInfo,FRAMEF_SPECIFY);
-
- // Move the text around
-
- SetAttrs((Object *)TextImage,
- IA_Left, WindowLeft - FramedSize.Left + DistX,
- IA_Top, WindowTop - FramedSize.Top + DistY,
- TAG_DONE);
-
- // Almost finished, now centre the frame around the text
-
- DoMethod((Object *)FrameImage,IM_FRAMEBOX,&TextImage->LeftEdge,&FramedSize,DrawInfo,NULL);
-
- SetAttrs((Object *)FrameImage,
- IA_Left, FramedSize.Left - DistX,
- IA_Top, FramedSize.Top - DistY,
- IA_Width, FramedSize.Width,
- IA_Height, FramedSize.Height,
- TAG_DONE);
-
- // Now link the objects together
-
- FillImage->NextImage = FrameImage;
- FrameImage->NextImage = TextImage;
-
- // Zap the dummy gadget and put the image inside
-
- memset(&Dummy,0,sizeof(Dummy));
-
- Dummy.Flags = GFLG_GADGIMAGE|GFLG_GADGHNONE;
- Dummy.GadgetRender = FillImage;
-
- // Put the gadget in
-
- /* ALWAYS */
- {
- LONG Left = FrameImage->LeftEdge,
- Top = FillImage->TopEdge + FillImage->Height;
-
- GadgetTable[GadgetInformation[1] - 1]->NextGadget = &Dummy;
-
- SetAttrs((Object *)FillImage,
- IA_Height, FillImage->Height + GadgetTable[0]->Height + RoomY,
- TAG_DONE);
-
- Height += GadgetTable[0]->Height + RoomY;
-
- if(GadgetInformation[1] > 1)
- {
- LONG Room = Width - FullButtonWidth,Count = GadgetInformation[1] - 1,i;
-
- Left = FrameImage->LeftEdge;
- Room += Count * RoomX;
-
- for(i = 0 ; i <= Count ; i++)
- {
- SetAttrs((Object *)GadgetTable[i],
- GA_Top, Top,
- GA_Left, Left,
- TAG_DONE);
-
- Left += GadgetTable[i]->Width + ((Room * (i + 1)) / Count - (Room * i) / Count);
- }
- }
- else
- {
- SetAttrs((Object *)GadgetTable[0],
- GA_Top, Top,
- GA_Left, Left + (FillImage->Width - GadgetTable[0]->Width) / 2,
- TAG_DONE);
- }
- }
-
- // Check if the window will fit on the screen
-
- if(Width <= Screen->Width && Height <= Screen->Height)
- {
- // Centre the body text strings
-
- /* ALWAYS */
- {
- struct IntuiText *This;
-
- for(This = BodyText ; This ; This = This->NextText)
- {
- This->ITextFont = Screen->Font;
- This->LeftEdge = (MoreData[5] - IntuiTextLength(This)) / 2;
- This->ITextFont = NULL;
- }
- }
-
- // Centre the window to open
-
- if(Parent)
- {
- WindowLeft = Parent -> LeftEdge + Parent -> BorderLeft;
- WindowTop = Parent -> TopEdge + Parent -> BorderTop;
- WindowWidth = Parent -> Width - (Parent -> BorderLeft + Parent -> BorderRight);
- WindowHeight = Parent -> Height - (Parent ->BorderTop + Parent -> BorderBottom);
-
- if((Left = WindowLeft + (WindowWidth - Width) / 2) < 0)
- Left = 0;
-
- if((Top = WindowTop + (WindowHeight - Height) / 2) < 0)
- Top = 0;
-
- GetScreenInfo(Screen,&ScreenLeft,&ScreenTop,&ScreenWidth,&ScreenHeight);
-
- if(Left < ScreenLeft || Left + Width > ScreenLeft + ScreenWidth)
- Left = -1;
-
- if(Top < ScreenTop || Top + Height > ScreenTop + ScreenHeight)
- Top = -1;
-
- if(Top == -1 || Left == -1)
- CentreWindow(Screen,Width,Height,&Left,&Top);
- }
- else
- CentreWindow(Screen,Width,Height,&Left,&Top);
-
- // Finally, open the window
-
- if(Window = OpenWindowTags(NULL,
- WA_Left, Left,
- WA_Top, Top,
- WA_Width, Width,
- WA_Height, Height,
- WA_Title, Title,
- WA_Flags, WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_RMBTRAP | WFLG_NOCAREREFRESH | WFLG_SIMPLE_REFRESH | WFLG_ACTIVATE,
- WA_IDCMP, IDCMP_GADGETUP | IDCMP_VANILLAKEY | IDCMP_RAWKEY,
- WA_CustomScreen, Screen,
- WA_Gadgets, GadgetTable[0],
- TAG_DONE))
- {
- struct IntuiMessage *Message;
- struct Gadget *MsgGadget;
- ULONG MsgClass;
- LONG MsgCode;
- struct Gadget *Gadget = NULL;
- BOOL Terminated = FALSE;
-
- do
- {
- WaitPort(Window->UserPort);
-
- while(Message = (struct IntuiMessage *)GetMsg(Window->UserPort))
- {
- MsgClass = Message->Class;
- MsgCode = Message->Code;
- MsgGadget = Message->IAddress;
-
- ReplyMsg((struct Message *)Message);
-
- switch(MsgClass)
- {
- case IDCMP_GADGETUP:
-
- Terminated = TRUE;
- Result = MsgGadget->GadgetID;
-
- break;
-
- case IDCMP_VANILLAKEY:
-
- MsgCode = ToUpper(MsgCode);
-
- switch(MsgCode)
- {
- case '\033':
- case 'B':
- case ('C' & 0x1F):
-
- Terminated = TRUE;
- Gadget = GadgetTable[GadgetInformation[1] - 1];
-
- break;
-
- case '\r':
- case 'V':
-
- Terminated = TRUE;
- Gadget = GadgetTable[0];
-
- break;
- }
-
- break;
-
- case IDCMP_RAWKEY:
-
- switch(MsgCode)
- {
- case HELP_CODE:
-
- GuideDisplay(CONTEXT_MAIN);
- break;
-
- default:
-
- if(MsgCode >= F01_CODE && MsgCode <= F10_CODE)
- {
- MsgCode -= F01_CODE;
-
- if(MsgCode < GadgetInformation[1])
- {
- Terminated = TRUE;
-
- Gadget = GadgetTable[MsgCode];
- }
- }
-
- break;
- }
-
- break;
- }
- }
- }
- while(!Terminated);
-
- if(Gadget)
- {
- STATIC ULONG SelectedTags[] = { GA_Selected,TRUE, TAG_DONE };
- STATIC ULONG DeselectedTags[] = { GA_Selected,FALSE, TAG_DONE };
-
- SetGadgetAttrsA(Gadget,Window,NULL,(struct TagItem *)SelectedTags);
- RefreshGList(Gadget,Window,NULL,1);
-
- DelayTime(0,80000);
-
- SetGadgetAttrsA(Gadget,Window,NULL,(struct TagItem *)DeselectedTags);
- RefreshGList(Gadget,Window,NULL,1);
- }
-
- CloseWindow(Window);
- }
- }
- }
-
- // Get rid of the images
-
- DisposeObject(FillImage);
- DisposeObject(FrameImage);
- DisposeObject(TextImage);
- }
-
- // And the buffers so much work went into...
-
- FreeVec(BodyText);
- FreeVec(GadgetText);
-
- if(GadgetTable)
- {
- LONG i;
-
- for(i = 0 ; i < GadgetInformation[1] ; i++)
- DisposeObject(GadgetTable[i]);
-
- FreeVec(GadgetTable);
- }
-
- DisposeObject(GadgetFrameImage);
-
- FreeScreenDrawInfo(Screen,DrawInfo);
- }
-
- if(PopBack)
- ScreenToBack(Screen);
-
- if(!Parent)
- UnlockPubScreen(NULL,Screen);
- }
-
- return(Result);
- }
-